// 文件名：array_protocol_header.cpp
// 目的：定义一个简单的报文头 PacketHeader，并提供序列化/反序列化（网络字节序）。
// 字段：
//   - version：协议版本；
//   - type：报文类型；
//   - payloadLength：负载长度（以网络字节序 Big-Endian 存储）。
// API：
//   - serialize()：将头部编码为固定长度数组（字节序转换）；
//   - parse(buffer)：从字节数组解析头部（字节序还原）。
// 演示：
//   - main 中将头部序列化为字节流，并以十六进制打印；随后解析并打印字段。
// 注意：
//   - 示例手动移位进行大小端转换（相当于 htons/ntohs 的内联形式）；
//   - kSize 固定为 4 字节，确保序列化长度一致；
//   - 实际协议中可加入校验和、魔数、保留位等；
//   - iostream 的进制状态需在输出后恢复 std::dec（示例已处理）。

#include <array>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <iostream>

struct PacketHeader {
    std::uint8_t version;
    std::uint8_t type;
    std::uint16_t payloadLength; // network byte order（序列化为大端）

    static constexpr std::size_t kSize = 4;

    // 序列化为字节数组（大端）
    std::array<std::uint8_t, kSize> serialize() const {
        std::array<std::uint8_t, kSize> buffer{};
        buffer[0] = version;
        buffer[1] = type;
        buffer[2] = static_cast<std::uint8_t>(payloadLength >> 8);   // 高字节
        buffer[3] = static_cast<std::uint8_t>(payloadLength & 0xFF); // 低字节
        return buffer;
    }

    // 从字节数组解析（按大端还原）
    static PacketHeader parse(const std::array<std::uint8_t, kSize>& buffer) {
        PacketHeader hdr{};
        hdr.version = buffer[0];
        hdr.type = buffer[1];
        hdr.payloadLength = static_cast<std::uint16_t>(buffer[2]) << 8 |
                            static_cast<std::uint16_t>(buffer[3]);
        return hdr;
    }
};

int main() {
    PacketHeader outgoing{1, 0x10, 512};
    auto raw = outgoing.serialize();

    std::cout << "Serialized header:";
    for (auto byte : raw) {
        std::cout << ' ' << std::hex << std::setw(2) << std::setfill('0')
                  << static_cast<int>(byte);
    }
    std::cout << std::dec << '\n'; // 恢复十进制

    PacketHeader incoming = PacketHeader::parse(raw);
    std::cout << "Parsed -> version: " << static_cast<int>(incoming.version)
              << ", type: " << static_cast<int>(incoming.type)
              << ", payloadLength: " << incoming.payloadLength << '\n';
    return 0;
}